package com.springboot.demo.controller;

import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport;
import com.google.code.kaptcha.impl.DefaultKaptcha;
import com.springboot.demo.entity.*;
import com.springboot.demo.entity.validate.PhoneGroup1;
import com.springboot.demo.entity.validate.user.IdGroup;
import com.springboot.demo.entity.validate.user.*;
import com.springboot.demo.service.UserService;
import com.springboot.demo.utils.*;
import io.swagger.annotations.*;
import lombok.extern.slf4j.Slf4j;
import org.hibernate.validator.constraints.Length;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import javax.validation.Valid;
import javax.validation.constraints.Min;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.Pattern;
import java.io.*;
import java.util.List;

/**
 * @author wubc683
 * @desc
 * @date 2021-07-26 10:12
 */
@RestController
@Api(tags = "用户接口")
@Slf4j
public class UserController {
    @Autowired
    UserService userService;
    @Autowired
    ImgCodeUtils imgCodeUtils;
    @Autowired
    SmsCodeUtils smsCodeUtils;
    @Autowired
    DefaultKaptcha defaultKaptcha;
    @Autowired
    ResponseUtils responseUtils;

//    @GetMapping(value = "/logout")
//    @ApiOperation("注销用户")
//    @ApiOperationSupport(order = 10)
//    public ResponseUtils logout() {
//        return responseUtils.buildSuccessResponse();
//    }

    @GetMapping(value = "/common/username/{username}")
    @ApiOperation("校验用户名是否被注册")
    @ApiOperationSupport(order = 20, includeParameters = {"username"})
    public ResponseUtils checkUsername(@Validated(UsernameGroup.class) User user) {
        userService.checkUsername(user.getUsername().trim());
        return responseUtils.buildSuccessResponse();
    }

    @GetMapping(value = "/common/phone/{phone}")
    @ApiOperation(value = "校验电话是否被注册")
    @ApiOperationSupport(order = 40, includeParameters = {"phone"})
    public ResponseUtils IsPhoneRegistered(@Validated({PhoneGroup.class, PhoneGroup1.class}) User user) {
        Boolean b = userService.isPhoneRegistered(user.getPhone());
        if (b) {
            return responseUtils.buildFailedResponse(ResponseResult.PHONE_IS_REGISTERED);
        }
        return responseUtils.buildSuccessResponse();
    }

    @PostMapping("/common/register")
    @ApiOperation(value = "注册")
    @ApiOperationSupport(order = 60, includeParameters = {"user.username", "user.password", "user.retryPassword",
            "user" + ".phone", "user.company", "user.companyAddr", "user.industryType", "user.smsCode"})
    public ResponseUtils register(@RequestBody @Validated(RegisterGroup.class) User user) {
        userService.saveUser(user);
        return responseUtils.buildSuccessResponse();
    }

    @PostMapping("/common/username")
    @ApiOperation("忘记用户名")
    @ApiOperationSupport(order = 71, includeParameters = {"user.phone", "user.smsCode"})
    public ResponseUtils findUsername(@Validated(value = {FindUsernameGroup.class}) @RequestBody User user) {
        String username = userService.findUsernameByPhone(user);
        return responseUtils.buildSuccessResponse(username);
    }

    @PutMapping("/common/pwd")
    @ApiOperation(value = "忘记密码", notes = "此接口用于未登录时的忘记密码功能")
    @ApiOperationSupport(order = 72, includeParameters = {"user.phone", "user.password", "user.retryPassword"
            , "user.smsCode"})
    public ResponseUtils forgetPwd(@Validated(value = {ForgetPwdGroup.class}) @RequestBody User user) {
        userService.updatePasswordByPhone(user);
        return responseUtils.buildSuccessResponse();
    }

    @GetMapping("/user")
    @ApiOperation(value = "获取用户信息", notes = "注意：手机号有状态，校验或者未校验")
    @ApiOperationSupport(order = 73)
    public ResponseUtils<User> getUserInfo() {
        Object principal = SecurityContextHolder.getContext().getAuthentication().getPrincipal();
        UserDetailsImpl userDetailsImpl = (UserDetailsImpl) principal;
        User implUser = userDetailsImpl.getUser();
        User userById = userService.getUserInfoById(implUser.getId());
        // 隐藏密码信息
        userById.setPassword("");
        return responseUtils.buildSuccessResponse(userById);
    }

    @PutMapping("/user")
    @ApiOperation(value = "修改用户信息", notes = "管理员用户手机号不能为空，普通关联用户可以为空，根据【isPhoneChecked】字段显示手机号状态：" +
            "未校验或者已校验，如果未校验或者用户改变了手机号，则增加按钮【校验】，按下会弹出手机号验证码输入框")
    @ApiOperationSupport(order = 75, includeParameters = {"user.username", "user.phone"})
    public ResponseUtils updateUserInfo(@Validated(value = {UsernameGroup.class, PhoneGroup.class, PhoneGroup1.class}) @RequestBody User user) {
        Object principal = SecurityContextHolder.getContext().getAuthentication().getPrincipal();
        UserDetailsImpl userDetailsImpl = (UserDetailsImpl) principal;
        User implUser = userDetailsImpl.getUser();
        userService.updateUserInfo(implUser.getId(), user);
        return responseUtils.buildSuccessResponse();
    }

    @PostMapping("/phone/validate")
    @ApiOperation(value = "校验电话", notes = "修改成功，手机号变成已校验")
    @ApiOperationSupport(order = 77, includeParameters = {"user.phone", "user.smsCode"})
    public ResponseUtils checkPhone(@Validated(value = {PhoneGroup.class, PhoneGroup1.class, SmsCodeGroup.class}) @RequestBody User user) {
        Object principal = SecurityContextHolder.getContext().getAuthentication().getPrincipal();
        UserDetailsImpl userDetailsImpl = (UserDetailsImpl) principal;
        User implUser = userDetailsImpl.getUser();
        userService.updatePhone(implUser.getId(), user);
        return responseUtils.buildSuccessResponse();
    }

    @PutMapping("/pwd")
    @ApiOperation(value = "修改密码")
    @ApiOperationSupport(order = 80, includeParameters = {"user.oldPassword", "user.password", "user.retryPassword"})
    public ResponseUtils updatePassword(@Validated({oldPasswordGroup.class, PasswordGroup.class,
            RetryPasswordGroup.class}) @RequestBody User user) {
        Object principal = SecurityContextHolder.getContext().getAuthentication().getPrincipal();
        UserDetailsImpl userDetailsImpl = (UserDetailsImpl) principal;
        User implUser = userDetailsImpl.getUser();
        // 更新密码信息
        userService.updatePassword(implUser.getId(), user);
        return responseUtils.buildSuccessResponse();
    }

    @GetMapping("/common/imgCode")
    @ApiOperation(value = "发送图形验证码", notes = "直接用img标签的src属性接收")
    @ApiOperationSupport(order = 90)
    public void sendImgCode(HttpServletRequest request, HttpServletResponse response) throws IOException {
        imgCodeUtils.create(request, response);
    }

    @GetMapping("/common/imgCode/{imgCode}/smsCode/{phone}")
    @ApiOperation(value = "发送短信验证码", notes = "增加说明信息：同一个手机号一天只能接收5次验证码,谨慎使用")
    @ApiOperationSupport(order = 100, includeParameters = {"imgCode", "phone"})
    public ResponseUtils sendSmsCode(HttpServletRequest request,
                                     @Validated({PhoneGroup.class, PhoneGroup1.class}) User user) {
        userService.checkImgCode(request, user.getImgCode().trim());
        String clientIp = null;
        // 获取请求真实ip,非代理ip
        if (request.getHeader("x-forwarded-for") == null) {
            clientIp = request.getRemoteAddr();
        } else {
            clientIp = request.getHeader("x-forwarded-for");
        }
        smsCodeUtils.send(clientIp, user.getPhone());
        return responseUtils.buildSuccessResponse();
    }

    @GetMapping("/profile/{id}")
    @ApiOperation(value = "获取头像", notes = "直接用img标签的src属性接收")
    @ApiOperationSupport(order = 110, includeParameters = "id")
    public void getProfile(@Validated(IdGroup.class) User user, HttpServletResponse response) throws IOException {
        Object principal = SecurityContextHolder.getContext().getAuthentication().getPrincipal();
        UserDetailsImpl userDetailsImpl = (UserDetailsImpl) principal;
        User implUser = userDetailsImpl.getUser();
        userService.getProfile(implUser.getId(), user.getId(), response);
    }

    @PutMapping("/profile")
    @ApiOperation("修改头像")
    @ApiOperationSupport(order = 110)
    public ResponseUtils updateProfile(@RequestPart(value = "profile") MultipartFile profile) throws Exception {
        Object principal = SecurityContextHolder.getContext().getAuthentication().getPrincipal();
        UserDetailsImpl userDetailsImpl = (UserDetailsImpl) principal;
        Long uid = userDetailsImpl.getUser().getId();
//        String path = Constant.PROFILE_PATH + "\\" + uid + "\\" + "profile"+uid+".png";
        String path = Constant.PROFILE_PATH + "/" + uid + "/" + "profile" + uid + ".png";
        FileUtils.upload(profile, path);
        return responseUtils.buildSuccessResponse();
    }

    @PostMapping("/relativeUser")
    @ApiOperation(value = "创建关联用户", notes = "注意：手机号可以为空,不能分配管理员权限，管理员只能是注册账号，唯一")
    @ApiOperationSupport(order = 120, includeParameters = {"user.username", "user.password", "user.retryPassword",
            "user.rid", "user.phone"})
    public ResponseUtils createRelativeAccount(
            @Validated(value = CreateRelativeAccountGroup.class) @RequestBody User user) {
        Object principal = SecurityContextHolder.getContext().getAuthentication().getPrincipal();
        UserDetailsImpl userDetailsImpl = (UserDetailsImpl) principal;
        User implUser = userDetailsImpl.getUser();
        userService.insertRelativeAccount(implUser.getId(), user);
        return responseUtils.buildSuccessResponse();
    }

    @DeleteMapping("/relativeUser/{id}")
    @ApiOperation("删除关联用户")
    @ApiOperationSupport(order = 130, includeParameters = {"id"})
    public ResponseUtils deleteRelativeAccount(@PathVariable @ApiParam(required = true) Long id) {
        Object principal = SecurityContextHolder.getContext().getAuthentication().getPrincipal();
        UserDetailsImpl userDetailsImpl = (UserDetailsImpl) principal;
        User implUser = userDetailsImpl.getUser();
        userService.deleteRelativeAccount(implUser.getId(), id);
        return responseUtils.buildSuccessResponse();
    }

    @PutMapping("/relativeUser")
    @ApiOperation(value = "修改关联用户", notes = "注意：手机号可以为空,不能分配管理员权限，管理员只能是注册账号，唯一")
    @ApiOperationSupport(order = 140, includeParameters = {"user.id", "user.username", "user.password", "user" +
            ".retryPassword", "user.rid", "user.phone"})
    public ResponseUtils updateRelativeAccount(
            @Validated(value = UpdateRelativeAccountGroup.class) @RequestBody User user) {
        Object principal = SecurityContextHolder.getContext().getAuthentication().getPrincipal();
        UserDetailsImpl userDetailsImpl = (UserDetailsImpl) principal;
        User implUser = userDetailsImpl.getUser();
        userService.updateRelativeAccount(implUser.getId(), user);
        return responseUtils.buildSuccessResponse();
    }

    @GetMapping("/relativeUser/{id}")
    @ApiOperation("获取关联用户信息")
    @ApiOperationSupport(order = 160, includeParameters = "id")
    public ResponseUtils<User> getRelativeAccount(@Validated(IdGroup.class) User user) {
        Object principal = SecurityContextHolder.getContext().getAuthentication().getPrincipal();
        UserDetailsImpl userDetailsImpl = (UserDetailsImpl) principal;
        User implUser = userDetailsImpl.getUser();
        User relativeAccount = userService.getRelativeAccount(implUser, user.getId());
        return responseUtils.buildSuccessResponse(relativeAccount);
    }

    @GetMapping("/relativeUsers")
    @ApiOperation("获取所有关联用户信息")
    @ApiOperationSupport(order = 160)
    public ResponseUtils<PageResult<List<User>>> getRelativeAccounts(@Valid PageRequest pageQuery) {
        Object principal = SecurityContextHolder.getContext().getAuthentication().getPrincipal();
        UserDetailsImpl userDetailsImpl = (UserDetailsImpl) principal;
        User user = userDetailsImpl.getUser();
        User userInfo = userService.getUserInfoById(user.getId());
        PageResult result = userService.getRelativeAccounts(userInfo, pageQuery);
        return responseUtils.buildSuccessResponse(result);
    }

    @GetMapping("/systemLog")
    @ApiOperation(value = "获取自身及其关联用户登录日志", notes = "管理员接口")
    @ApiOperationSupport(order = 170)
    public ResponseUtils<PageResult<List<SystemLog>>> getSystemLog(@Valid PageRequest pageQuery) {
        Object principal = SecurityContextHolder.getContext().getAuthentication().getPrincipal();
        UserDetailsImpl userDetailsImpl = (UserDetailsImpl) principal;
        User user = userDetailsImpl.getUser();
        PageResult result = userService.getSystemLog(user, pageQuery);
        return responseUtils.buildSuccessResponse(result);
    }

    @GetMapping(value = "/username")
    @ApiOperation(value = "根据用户名查找用户", notes = "返回用户名集合,模糊匹配")
    @ApiOperationSupport(order = 180)
    public ResponseUtils<List<String>> getUserByName(
            @RequestParam(value = "username", required = false)
            @ApiParam("1~32位") @Length(min = 1, max = 32) String username,
            @RequestParam(value = "deviceClusterId", required = false)
            @ApiParam(value = "查找设备群用户时加上此参数,用于过滤设备群中已有用户", required = false) Long deviceClusterId) {
        Object principal = SecurityContextHolder.getContext().getAuthentication().getPrincipal();
        UserDetailsImpl userDetailsImpl = (UserDetailsImpl) principal;
        User implUser = userDetailsImpl.getUser();
        User userInfoById = userService.getUserInfoById(implUser.getId());
        List<String> userByName = userService.getUserByName(userInfoById, username, deviceClusterId);
        return responseUtils.buildSuccessResponse(userByName);
    }

    @GetMapping("/admin/users")
    @ApiOperation(value = "获取所有注册管理员用户信息", notes = "超级管理员接口，用于后台管理，续费，激活等")
    @ApiOperationSupport(order = 185)
    public ResponseUtils<PageResult<List<User>>> getAllAdminUser(@Valid PageRequest pageRequest) {
        PageResult allAdminUser = userService.getAllAdminUser(pageRequest);
        return responseUtils.buildSuccessResponse(allAdminUser);
    }

    @PutMapping("/user/{id}/enabled")
    @ApiOperation(value = "激活用户", notes = "超级管理员接口，注册账号必须后台手动激活才能使用")
    @ApiOperationSupport(order = 190)
    public ResponseUtils activeUser(@PathVariable("id") Long regId) {
        Object principal = SecurityContextHolder.getContext().getAuthentication().getPrincipal();
        UserDetailsImpl userDetailsImpl = (UserDetailsImpl) principal;
        User implUser = userDetailsImpl.getUser();
        userService.activeUser(implUser.getId(), regId);
        return responseUtils.buildSuccessResponse();
    }

    @PutMapping("/user/{id}/locked/{locked}")
    @ApiOperation(value = "锁定用户", notes = "使账号无法登录，locked：0表示解锁，1表示锁定")
    @ApiOperationSupport(order = 200)
    public ResponseUtils lockUser(@PathVariable("id") Long userId,
                                  @PathVariable("locked") Integer locked) {
        Object principal = SecurityContextHolder.getContext().getAuthentication().getPrincipal();
        UserDetailsImpl userDetailsImpl = (UserDetailsImpl) principal;
        User implUser = userDetailsImpl.getUser();
        userService.lockUser(implUser.getId(), userId, locked);
        return responseUtils.buildSuccessResponse();
    }

    @PutMapping("/user/{id}/expire/{month}")
    @ApiOperation(value = "给用户账号续期", notes = "超级管理员接口，month:表示给用户续期几个月,3,6,12,24")
    @ApiOperationSupport(order = 210)
    public ResponseUtils addUserExpireDate(@PathVariable("id") Long regId,
                                           @PathVariable("month") @Min(0) Integer month) {
        Object principal = SecurityContextHolder.getContext().getAuthentication().getPrincipal();
        UserDetailsImpl userDetailsImpl = (UserDetailsImpl) principal;
        User implUser = userDetailsImpl.getUser();
        userService.addUserExpireDate(implUser.getId(), regId, month);
        return responseUtils.buildSuccessResponse();
    }
}